package com.ssy.lingxi.pay.serviceimpl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.message.api.constant.MessageTemplateCode;
import com.ssy.lingxi.message.api.vo.request.SystemMessageRequest;
import com.ssy.lingxi.pay.api.model.vo.request.CreditBillInitVO;
import com.ssy.lingxi.pay.common.*;
import com.ssy.lingxi.pay.entity.CreditBillDO;
import com.ssy.lingxi.pay.entity.CreditDO;
import com.ssy.lingxi.pay.model.vo.request.PageQueryCreditOverdueVO;
import com.ssy.lingxi.pay.model.vo.response.*;
import com.ssy.lingxi.pay.repository.CreditBillRepository;
import com.ssy.lingxi.pay.repository.CreditRepository;
import com.ssy.lingxi.pay.service.ICreditBillService;
import com.ssy.lingxi.pay.service.ICreditTradeRecordService;
import com.ssy.lingxi.pay.service.IFeignService;
import com.ssy.lingxi.pay.utils.CreditUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 *  授信账单接口实现
 * @author 伍将
 * @date 2020/8/21
 * @version 2.0.0
 */
@Service
public class CreditBillServiceImpl implements ICreditBillService {

    @Resource
    private CreditBillRepository billRepository;

    @Resource
    private CreditRepository creditRepository;

    @Resource
    private ICreditTradeRecordService tradeRecordService;

    @Resource
    private IFeignService feignService;

    /**
     * 初始化授信账单
     * @author 伍将
     * @date 2020/8/21
     * @param initVO:
     * @return com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> init(CreditBillInitVO initVO) {

        Date time = DateUtil.parse(initVO.getInitDate(), "yyyy-MM-dd");
        // 获取账单日期
        Integer billDay = DateUtil.dayOfMonth(time);
        // 账单所属时间（格式：当月第一天0点0分时间戳）
        Long billBelongTime = DateUtil.beginOfMonth(time).getTime();

        // 查询授信列表
        List<CreditDO> creditDOList = creditRepository.findByBillDayAndStatusIsNot(billDay, CreditStatusEnum.UN_APPLY.getCode());
        if (creditDOList.size() > 0) {

            // 查询已存在账单列表
            List<CreditBillDO> billDOList = billRepository.findByBillBelongTimeAndBillDay(billBelongTime, billDay);

            // 定义新增账单列表
            List<CreditBillDO> addList = creditDOList.stream().filter(
                    item -> !billDOList.stream()
                            .map(CreditBillDO::getCreditId)
                            .collect(Collectors.toList())
                            .contains(item.getId()))
                    .collect(Collectors.toList())
                    .stream().map(r -> {
                        CreditBillDO addDo = new CreditBillDO();
                        addDo.setCreditId(r.getId());
                        addDo.setBillBelongTime(billBelongTime);
                        addDo.setBillDay(r.getBillDay());
                        addDo.setRepayPeriod(r.getRepayPeriod());
                        addDo.setCreateTime(System.currentTimeMillis());
                        Date expireTime = CreditUtil.getExpireTime(time, r.getBillDay(), r.getRepayPeriod());
                        addDo.setExpireTime(expireTime.getTime());
                        return addDo;
                    }).collect(Collectors.toList());

            // 新增授信账单列表
            if (addList.size() > 0) {
                billRepository.saveAll(addList);
            }
        }

        return Wrapper.success();
    }

    /**
     * 初始化逾期
     * @author 伍将
     * @date 2020/8/28
     * @param initVO:
     * @return com.ssy.lingxi.common.response.Wrapper
     **/
    @Override
    public Wrapper<Void> initOverdue(CreditBillInitVO initVO) {

        Date time = DateUtil.parseDateTime(initVO.getInitDate());
        // 查询逾期账单
        List<CreditBillDO> billDOList = getOverdueBillList(time.getTime());
        if (billDOList.size() > 0) {

            List<Long> creditIdList = billDOList.stream().map(CreditBillDO::getCreditId).collect(Collectors.toList());
            List<CreditDO> creditDOList = creditRepository.findByIdIn(creditIdList);

            // 修改授信记录的到期时间为对应逾期账单时间，但不能晚于上次到期时间
            List<CreditDO> updateCreditDOList = creditDOList.stream().peek(item -> {
                CreditBillDO billDO = billDOList.stream().filter(bill -> bill.getCreditId().equals(item.getId())).findFirst().orElse(null);
                if (billDO != null && billDO.getExpireTime() <= item.getExpireTime()) {
                    item.setRePayStatus(CreditRepayStatusEnum.OVERDUE.getCode());
                    item.setExpireTime(billDO.getExpireTime());
                    item.setUpdateTime(System.currentTimeMillis());
                }
            }).collect(Collectors.toList());

            // 授信数据入库
            if (updateCreditDOList.size() > 0) {
                creditRepository.saveAll(updateCreditDOList);
            }
        }

        return Wrapper.success();
    }

    /**
     * 根据到期时间查询逾期账单
     * @author 伍将
     * @date 2020/8/28
     * @param expireTime:
     * @return java.util.List<com.ssy.lingxi.pay.entity.CreditBillDO>
     **/
    private List<CreditBillDO> getOverdueBillList(Long expireTime) {
        // 组装查询条件
        Specification<CreditBillDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            // 指定到期日期
            list.add(criteriaBuilder.equal(root.get("expireTime").as(Long.class), expireTime));
            // 账单额度大于已还额度
            list.add(criteriaBuilder.greaterThan(root.get("billQuota").as(Long.class), root.get("repayQuota").as(Long.class)));
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        return billRepository.findAll(spec);
    }

    /**
     * 根据授信id获取授信账单下拉框
     * @author 伍将
     * @date 2020/8/21
     * @param creditId:
     * @return com.ssy.lingxi.common.response.Wrapper<java.util.List < com.ssy.lingxi.pay.model.vo.response.CreditBillSelectVO>>
     **/
    @Override
    public Wrapper<List<CreditBillSelectVO>> getSelect(Long creditId) {

        List<CreditBillDO> billDOList = billRepository.findByCreditIdOrderByBillBelongTimeDesc(creditId);

        List<CreditBillSelectVO> result = new ArrayList<>();
        for (int i = 0; i < billDOList.size(); i++) {
            // 当前账单
            CreditBillDO currentItem = billDOList.get(i);
            // 下个账单
            CreditBillDO nextItem = null;
            if (i < billDOList.size() - 1) {
                nextItem = billDOList.get(i + 1);
            }

            CreditBillSelectVO vo = new CreditBillSelectVO();
            vo.setId(currentItem.getId());
            Date startDate;
            Date endDate;
            if (nextItem == null) {
                startDate = DateUtil.offsetDay(DateUtil.date(currentItem.getBillBelongTime()), -1 + currentItem.getBillDay());
                endDate = DateUtil.offsetMonth(startDate, 1);
            } else {
                startDate = DateUtil.offsetDay(DateUtil.date(currentItem.getBillBelongTime()), nextItem.getBillDay());
                Date tmpDate = DateUtil.offsetDay(DateUtil.date(currentItem.getBillBelongTime()), -1 + currentItem.getBillDay());
                endDate = DateUtil.offsetMonth(tmpDate, 1);
            }
            String name = (DateUtil.format(startDate, "yyyy/MM/dd") + " ~ " + DateUtil.format(endDate, "yyyy/MM/dd"));
            vo.setName(name);

            result.add(vo);
        }

        return Wrapper.success(result);
    }

    /**
     * 获取授信账单详情
     * @author 伍将
     * @date 2020/8/21
     * @param id:
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.pay.model.vo.response.CreditBillDetailVO>
     **/
    @Override
    public Wrapper<CreditBillDetailVO> getDetail(Long id) {
        return getDetail(null,id);
    }

    /**
     * 查询授信详情
     * @param id:
     * @return
     */
    @Override
    public Wrapper<CreditBillDetailVO> getDetail(UserLoginCacheDTO user, Long id) {
        CreditBillDO billDO = billRepository.findById(id).orElse(null);
        if (billDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_BILL_NOT_EXIST);
        }
        CreditDO creditDO = creditRepository.findById(billDO.getCreditId()).orElse(null);
        if (creditDO == null) {
            throw new BusinessException(ResponseCode.PAY_CREDIT_NOT_EXIST);
        }
        if(user!=null){
            List<Long> memberIds = Stream.of(creditDO.getMemberId(), creditDO.getParentMemberId()).collect(Collectors.toList());
            if(!memberIds.contains(user.getMemberId())){
                throw new BusinessException(ResponseCode.PAY_CREDIT_NOT_EXIST);
            }
        }
        CreditBillDetailVO result = new CreditBillDetailVO();
        // 计算账单开始时间
        Date startDate = DateUtil.offsetDay(DateUtil.date(billDO.getBillBelongTime()), -1 + billDO.getBillDay());
        // 账单结束时间在开始时间基础上增加一个月
        Date endDate = DateUtil.offsetMonth(startDate, 1);
        String name = (DateUtil.format(startDate, "yyyy/MM/dd") + " ~ " + DateUtil.format(endDate, "yyyy/MM/dd"));
        result.setBillName(name);
        result.setBillQuota(billDO.getBillQuota());
        result.setResidueRepayQuota(BigDecimal.valueOf(billDO.getBillQuota() - billDO.getRepayQuota()).setScale(2, RoundingMode.HALF_UP).doubleValue());    //剩余应还额度=账单额度-偿还额度
        result.setBillDay(billDO.getBillDay());
        result.setRepayPeriod(billDO.getRepayPeriod());
        result.setExpireTime(DateUtil.format(DateUtil.date(billDO.getExpireTime()), "yyyy-MM-dd"));
        result.setBillExpireTime(billDO.getExpireTime());
        // 如果剩余还款为0，到期日期为0
        if (result.getResidueRepayQuota() <= 0) {
            result.setExpireDay(0L);
        } else {
            int overdueDay = CreditUtil.differentDays(new Date(), DateUtil.date(billDO.getExpireTime()));
            result.setExpireDay((long) overdueDay);
        }
        if (billDO.getLastRepayDate() > 0) {
            result.setLastRepayDate(DateUtil.format(DateUtil.date(billDO.getLastRepayDate()), "yyyy-MM-dd"));
        } else {
            result.setLastRepayDate("-");
        }
        result.setMemberId(creditDO.getParentMemberId());
        result.setMemberRoleId(creditDO.getParentMemberRoleId());

        return Wrapper.success(result);
    }

    @Override
    public Wrapper<CreditBillDetailVO> getDetailByMobile(Long id) {
        Wrapper<CreditBillDetailVO> wrapper = getDetail(id);
        if (wrapper.getCode() == ResponseCode.SUCCESS.getCode()&&wrapper.getData().getBillExpireTime()!=null) {
            String cnDate = DateUtil.formatChineseDate(new Date(wrapper.getData().getBillExpireTime()), false);
            wrapper.getData().setExpireTime(cnDate);
        }
        return wrapper;
    }

    /**
     * 分页查询授信逾期
     * @author 伍将
     * @date 2020/8/21
     * @param pageVO:
     * @return com.ssy.lingxi.common.response.Wrapper<com.ssy.lingxi.common.response.PageData < com.ssy.lingxi.pay.model.vo.response.CreditOverduePageQueryVO>>
     **/
    @Override
    public Wrapper<PageData<CreditOverduePageQueryVO>> pageOverdue(PageQueryCreditOverdueVO pageVO) {

        // 组装查询条件
        Specification<CreditBillDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            // 指定授信
            list.add(criteriaBuilder.equal(root.get("creditId").as(Long.class), pageVO.getCreditId()));
            // 账单到期日期小于系统当前时间
            list.add(criteriaBuilder.lessThan(root.get("expireTime").as(Long.class), System.currentTimeMillis()));
            list.add(criteriaBuilder.or(
                    // 还清时间大于到期时间
                    criteriaBuilder.greaterThan(root.get("payOffDate").as(Long.class), root.get("expireTime").as(Long.class)),
                    // 还款额度小于账单额度
                    criteriaBuilder.lessThan(root.get("repayQuota").as(Long.class), root.get("billQuota").as(Long.class))
            ));
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // 组装分页参数（按审批时间顺序排序）
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("expireTime").descending());

        // 分页查询数据
        Page<CreditBillDO> result = billRepository.findAll(spec, page);

        List<CreditOverduePageQueryVO> resultList = null;
        if (result.getContent().size() > 0) {

            // 组装账单对应时间范围名称
            List<CreditBillDO> billDOList = billRepository.findByCreditIdOrderByBillBelongTimeDesc(pageVO.getCreditId());
            List<CreditBillSelectVO> billSelectList = new ArrayList<>();
            for (int i = 0; i < billDOList.size(); i++) {
                // 当前账单
                CreditBillDO currentItem = billDOList.get(i);
                // 下个账单
                CreditBillDO nextItem = null;
                if (i < billDOList.size() - 1) {
                    nextItem = billDOList.get(i + 1);
                }

                CreditBillSelectVO vo = new CreditBillSelectVO();
                vo.setId(currentItem.getId());
                Date startDate;
                Date endDate;
                if (nextItem == null) {
                    startDate = DateUtil.offsetDay(DateUtil.date(currentItem.getBillBelongTime()), -1 + currentItem.getBillDay());
                    endDate = DateUtil.offsetMonth(startDate, 1);
                } else {
                    startDate = DateUtil.offsetDay(DateUtil.date(currentItem.getBillBelongTime()), nextItem.getBillDay());
                    Date tmpDate = DateUtil.offsetDay(DateUtil.date(currentItem.getBillBelongTime()), -1 + currentItem.getBillDay());
                    endDate = DateUtil.offsetMonth(tmpDate, 1);
                }
                String name = (DateUtil.format(startDate, "yyyy/MM/dd") + " ~ " + DateUtil.format(endDate, "yyyy/MM/dd"));
                vo.setName(name);
                billSelectList.add(vo);
            }


            // 获取逾期的付款记录
            List<Long> billIdList = result.getContent().stream().map(CreditBillDO::getId).collect(Collectors.toList());
            Wrapper<List<CreditOverdueTradeRecordVO>> tradeRecordList = tradeRecordService.getTradeRecordList(billIdList, CreditTradeOperationEnum.REPAY.getCode(), CreditTradeStatusEnum.CONFIRM_RECEIPT.getCode());

            // 组装返回数据
            resultList = result.getContent().stream().map(r -> {
                CreditOverduePageQueryVO queryVO = new CreditOverduePageQueryVO();
                // 逾期天数=还清日期-账单最后还款日期
                int overdueDay = CreditUtil.differentDays(DateUtil.date(r.getExpireTime()), new Date());
                queryVO.setOverdueDay((long) overdueDay);
                billSelectList.stream().filter(s -> s.getId().equals(r.getId())).findFirst().ifPresent(selectVO -> queryVO.setBillName(selectVO.getName()));
                queryVO.setBillQuota(r.getBillQuota());
                queryVO.setLastRepayDate(null != r.getLastRepayDate() && r.getLastRepayDate() > 0 ? DateUtil.format(DateUtil.date(r.getLastRepayDate()), "yyyy-MM-dd") : "-");
                queryVO.setLastRepayQuota(r.getLastRepayQuota());
                queryVO.setPayOffDate(null != r.getPayOffDate() && r.getPayOffDate() > 0 ? DateUtil.format(DateUtil.date(r.getPayOffDate()), "yyyy-MM-dd") : "-");

                // 赋值逾期交易记录
                if (tradeRecordList != null && tradeRecordList.getCode() == ResponseCode.SUCCESS.getCode()) {
                    List<CreditOverdueTradeRecordVO> recordList = tradeRecordList.getData().stream()
                            .filter(recordVO -> recordVO.getBillId().equals(r.getId()))
                            .peek(item -> {
                                // 逾期天数=交易时间-最后还款日期
                                item.setOverdueDay(DateUtil.between(DateUtil.parse(item.getTradeTime()), DateUtil.date(r.getExpireTime()), DateUnit.DAY));
                            }).collect(Collectors.toList());

                    queryVO.setTradeList(recordList);
                }

                return queryVO;
            }).collect(Collectors.toList());

        }

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * App端分页查询逾期记录
     * @author 伍将
     * @date 2021/3/9
     * @param pageVO: 分页请求参数
     * @return 操作结果
     **/
    @Override
    public Wrapper<PageData<CreditOverduePageQueryAppVO>> pageOverdueByApp(PageQueryCreditOverdueVO pageVO) {

        // 组装查询条件
        Specification<CreditBillDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            // 指定授信
            list.add(criteriaBuilder.equal(root.get("creditId").as(Long.class), pageVO.getCreditId()));
            // 账单到期日期小于系统当前时间
            list.add(criteriaBuilder.lessThan(root.get("expireTime").as(Long.class), System.currentTimeMillis()));
            list.add(criteriaBuilder.or(
                    // 还清时间大于到期时间
                    criteriaBuilder.greaterThan(root.get("payOffDate").as(Long.class), root.get("expireTime").as(Long.class)),
                    // 还款额度小于账单额度
                    criteriaBuilder.lessThan(root.get("repayQuota").as(Long.class), root.get("billQuota").as(Long.class))
            ));
            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // 组装分页参数（按审批时间顺序排序）
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("expireTime").descending());

        // 分页查询数据
        Page<CreditBillDO> result = billRepository.findAll(spec, page);

        List<CreditOverduePageQueryAppVO> resultList = null;
        if (result.getContent().size() > 0) {

            // 获取逾期的付款记录
            List<Long> billIdList = result.getContent().stream().map(CreditBillDO::getId).collect(Collectors.toList());
            Wrapper<List<CreditOverdueTradeRecordAppVO>> tradeRecordList = tradeRecordService.getTradeRecordListByApp(billIdList, CreditTradeOperationEnum.REPAY.getCode(), CreditTradeStatusEnum.CONFIRM_RECEIPT.getCode());

            // 组装返回数据
            resultList = result.getContent().stream().map(r -> {
                CreditOverduePageQueryAppVO queryVO = new CreditOverduePageQueryAppVO();

                // 计算账单开始时间
                Date startDate = DateUtil.offsetDay(DateUtil.date(r.getBillBelongTime()), -1 + r.getBillDay());
                // 账单结束时间在开始时间基础上增加一个月
                Date endDate = DateUtil.offsetMonth(startDate, 1);
                // 逾期天数=还清日期-账单最后还款日期
                queryVO.setOverdueDay(DateUtil.between(new Date(), DateUtil.date(r.getExpireTime()), DateUnit.DAY));
                String name = (DateUtil.format(startDate, "yyyy/MM/dd") + " ~ " + DateUtil.format(endDate, "yyyy/MM/dd"));
                queryVO.setBillName(name);
                queryVO.setBillQuota(r.getBillQuota());
                queryVO.setLastRepayDate(null != r.getLastRepayDate() && r.getLastRepayDate() > 0 ? DateUtil.format(DateUtil.date(r.getLastRepayDate()), "yyyy-MM-dd") : "-");
                queryVO.setLastRepayQuota(r.getLastRepayQuota());
                queryVO.setPayOffDate(null != r.getPayOffDate() && r.getPayOffDate() > 0 ? DateUtil.format(DateUtil.date(r.getPayOffDate()), "yyyy-MM-dd") : "-");

                // 赋值逾期交易记录
                if (tradeRecordList != null && tradeRecordList.getCode() == ResponseCode.SUCCESS.getCode()) {
                    List<CreditOverdueTradeRecordAppVO> recordList = tradeRecordList.getData().stream()
                            .filter(recordVO -> recordVO.getBillId().equals(r.getId()))
                            .peek(item -> {
                                // 逾期天数=交易时间-最后还款日期
                                item.setOverdueDay(DateUtil.between(DateUtil.date(item.getTradeTime()), DateUtil.date(r.getExpireTime()), DateUnit.DAY));
                            }).collect(Collectors.toList());

                    queryVO.setTradeList(recordList);
                }

                return queryVO;
            }).collect(Collectors.toList());

        }

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    /**
     * 还款通知
     * @author 伍将
     * @date 2020/12/21
     * @param time:
     * @return:
     **/
    @Override
    public Wrapper<Void> repayNotice(String time) {

        // 查询指定时间账单
        List<CreditBillDO> billDOList = billRepository.findAllByExpireTime(DateUtil.parseDateTime(time).getTime());
        if (billDOList.size() > 0) {

            // 查询授信
            List<Long> creditIdList = billDOList.stream().map(CreditBillDO::getCreditId).collect(Collectors.toList());
            List<CreditDO> creditDOList = creditRepository.findByIsUsableAndIdIn(CommonBooleanEnum.YES.getCode(), creditIdList);

            if (creditDOList != null && creditDOList.size() > 0) {
                // 已出逾期账单发送系统消息通知
                List<SystemMessageRequest> requestList = billDOList.stream().map(r -> {
                    SystemMessageRequest request = new SystemMessageRequest();
                    CreditDO creditDO = creditDOList.stream().filter(credit -> credit.getId().equals(r.getCreditId())).findFirst().orElse(null);
                    request.setMemberId(creditDO != null ? creditDO.getMemberId() : 0L);
                    request.setRoleId(creditDO != null ? creditDO.getMemberRoleId() : 0L);
                    request.setMessageNotice(MessageTemplateCode.repayment);
                    List<String> params = new ArrayList<>();
                    double notYetQuota = r.getBillQuota() - r.getRepayQuota();
                    params.add(Double.toString(notYetQuota));
                    params.add(DateUtil.format(DateUtil.date(r.getExpireTime()), "yyyy-MM-dd"));
                    request.setParams(params);
                    return request;
                }).collect(Collectors.toList());
                if (requestList.size() > 0) {
                    feignService.batchSendSystemMessage(requestList);
                }
            }
        }

        return Wrapper.success();
    }

    /**
     * 逾期通知
     * @author 伍将
     * @date 2020/12/21
     * @param time:
     * @return:
     **/
    @Override
    public Wrapper<Void> overdueNotice(String time) {

        // 查询逾期账单
        List<CreditBillDO> billDOList = getOverdueBillList(DateUtil.parseDateTime(time).getTime());
        if (billDOList.size() > 0) {

            // 查询授信
            List<Long> creditIdList = billDOList.stream().map(CreditBillDO::getCreditId).collect(Collectors.toList());
            List<CreditDO> creditDOList = creditRepository.findByIdIn(creditIdList);

            if (creditDOList != null && creditDOList.size() > 0) {
                // 已出逾期账单发送系统消息通知
                List<SystemMessageRequest> requestList = billDOList.stream().map(r -> {
                    SystemMessageRequest request = new SystemMessageRequest();
                    CreditDO creditDO = creditDOList.stream().filter(credit -> credit.getId().equals(r.getCreditId())).findFirst().orElse(null);
                    request.setMemberId(creditDO != null ? creditDO.getMemberId() : 0L);
                    request.setRoleId(creditDO != null ? creditDO.getMemberRoleId() : 0L);
                    request.setMessageNotice(MessageTemplateCode.overdue);
                    List<String> params = new ArrayList<>();
                    double notYetQuota = r.getBillQuota() - r.getRepayQuota();
                    params.add(Double.toString(notYetQuota));
                    params.add(DateUtil.format(DateUtil.date(r.getExpireTime()), "yyyy-MM-dd"));
//                    Long overdueDay = DateUtil.between(DateUtil.date(r.getExpireTime()), new Date(), DateUnit.DAY, false);
                    int overdueDay = CreditUtil.differentDays(DateUtil.date(r.getExpireTime()), new Date());
                    params.add(Integer.toString(overdueDay));
                    request.setParams(params);
                    return request;
                }).collect(Collectors.toList());
                if (requestList.size() > 0) {
                    feignService.batchSendSystemMessage(requestList);
                }
            }
        }

        return Wrapper.success();
    }

    /**
     * 账单通知
     * @author 伍将
     * @date 2020/12/21
     * @param billTime:
     * @return:
     **/
    @Override
    public Wrapper<Void> billNotice(String billTime) {

        Date time = DateUtil.parse(billTime, "yyyy-MM-dd");
        // 获取账单日期
        Integer billDay = DateUtil.dayOfMonth(time);
        // 账单所属时间（格式：前一月第一天0点0分时间戳）
        Long billBelongTime = DateUtil.beginOfMonth(DateUtil.offsetMonth(time, -1)).getTime();

        // 查询指定时间账单
        List<CreditBillDO> billDOList = billRepository.findByBillBelongTimeAndBillDay(billBelongTime, billDay);
        if (billDOList.size() > 0) {

            // 查询授信
            List<Long> creditIdList = billDOList.stream().map(CreditBillDO::getCreditId).collect(Collectors.toList());
            List<CreditDO> creditDOList = creditRepository.findByIdIn(creditIdList);

            if (creditDOList != null && creditDOList.size() > 0) {
                // 已出逾期账单发送系统消息通知
                List<SystemMessageRequest> requestList = billDOList.stream().map(r -> {
                    SystemMessageRequest request = new SystemMessageRequest();
                    CreditDO creditDO = creditDOList.stream().filter(credit -> credit.getId().equals(r.getCreditId())).findFirst().orElse(null);
                    request.setMemberId(creditDO != null ? creditDO.getMemberId() : 0L);
                    request.setRoleId(creditDO != null ? creditDO.getMemberRoleId() : 0L);
                    request.setMessageNotice(MessageTemplateCode.charge_off);
                    List<String> params = new ArrayList<>();
                    double notYetQuota = r.getBillQuota() - r.getRepayQuota();
                    params.add(Double.toString(notYetQuota));
                    params.add(DateUtil.format(DateUtil.date(r.getExpireTime()), "yyyy-MM-dd"));
                    request.setParams(params);
                    return request;
                }).collect(Collectors.toList());
                if (requestList.size() > 0) {
                    feignService.batchSendSystemMessage(requestList);
                }
            }
        }

        return Wrapper.success();
    }
}
